package io.kiki.stack.http.feign.form.multipart;

import feign.codec.EncodeException;
import lombok.val;

import java.net.URLConnection;

import static io.kiki.stack.http.feign.form.ContentProcessor.CRLF;

/**
 * A base writer class.
 *
 * @author Artem Labazin
 */
public abstract class AbstractWriter implements Writer {

    @Override
    public void write(Output output, String boundary, String key, Object value) throws EncodeException {
        output.write("--").write(boundary).write(CRLF);
        write(output, key, value);
        output.write(CRLF);
    }

    /**
     * Writes data for it's children.
     *
     * @param output output writer.
     * @param key    name for piece of data.
     * @param value  piece of data.
     * @throws EncodeException in case of write errors
     */
    @SuppressWarnings({"PMD.UncommentedEmptyMethodBody", "PMD.EmptyMethodInAbstractClassShouldBeAbstract"})
    protected void write(Output output, String key, Object value) throws EncodeException {
    }

    /**
     * Writes file's metadata.
     *
     * @param output      output writer.
     * @param name        name for piece of data.
     * @param fileName    file name.
     * @param contentType type of file content. May be the {@code null}, in that case it will be
     *                    determined by file name.
     */
    protected void writeFileMetadata(Output output, String name, String fileName, String contentType) {
        val contentDespositionBuilder = new StringBuilder().append("Content-Disposition: form-data; name=\"").append(name).append("\"");
        if (fileName != null) {
            contentDespositionBuilder.append("; ").append("filename=\"").append(fileName).append("\"");
        }

        String fileContentType = contentType;
        if (fileContentType == null) {
            if (fileName != null) {
                fileContentType = URLConnection.guessContentTypeFromName(fileName);
            }
            if (fileContentType == null) {
                fileContentType = "application/octet-stream";
            }
        }

        val string = new StringBuilder().append(contentDespositionBuilder.toString()).append(CRLF).append("Content-Type: ").append(fileContentType).append(CRLF).append("Content-Transfer-Encoding: binary").append(CRLF).append(CRLF).toString();

        output.write(string);
    }
}
